home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / snip1292.zip / JDN.C < prev    next >
C/C++ Source or Header  |  1992-12-26  |  5KB  |  125 lines

  1. /* jdn.c -- Julian Day Number computation
  2. **
  3. ** public domain Julian Day Number functions
  4. **
  5. ** Based on formulae originally posted by
  6. **    Tom Van Flandern / Washington, DC / metares@well.sf.ca.us
  7. **       in the UseNet newsgroup sci.astro.
  8. **    Reposted 14 May 1991 in FidoNet C Echo conference by
  9. **       Paul Schlyter (Stockholm)
  10. ** Minor corrections, added JDN to julian, and recast into C by
  11. **    Raymond Gardner  Englewood, Colorado
  12. **
  13. ** Synopsis:
  14. **      long ymd_to_jdn(int year, int month, int day, int julian_flag)
  15. **      void jdn_to_ymd(long jdn, int *year, int *month, int *day,
  16. **                                                      int julian_flag)
  17. **      year is negative if BC
  18. **      if julian_flag is >  0, use Julian calendar
  19. **      if julian_flag is == 0, use Gregorian calendar
  20. **      if julian_flag is <  0, routines decide based on date
  21. **
  22. ** These routines convert Gregorian and Julian calendar dates to and 
  23. ** from Julian Day Numbers.  Julian Day Numbers (JDN) are used by 
  24. ** astronomers as a date/time measure independent of calendars and 
  25. ** convenient for computing the elapsed time between dates.  The JDN 
  26. ** for any date/time is the number of days (including fractional 
  27. ** days) elapsed since noon, 1 Jan 4713 BC.  Julian Day Numbers were 
  28. ** originated by Joseph Scaliger in 1582 and named after his father 
  29. ** Julius, not after Julius Caesar.  They are not related to the 
  30. ** Julian calendar. 
  31. ** 
  32. ** For dates from 1 Jan 4713 BC thru 12 Dec Feb 32766 AD, ymd_to_jdn() 
  33. ** will give the JDN for noon on that date.  jdn_to_ymd() will compute 
  34. ** the year, month, and day from the JDN.  Years BC are given (and 
  35. ** returned) as negative numbers.  Note that there is no year 0 BC; 
  36. ** the day before 1 Jan 1 AD is 31 Dec 1 BC.  Note also that 1 BC, 
  37. ** 5 BC, etc. are leap years.
  38. ** 
  39. ** Pope Gregory XIII decreed that the Julian calendar would end on 
  40. ** 4 Oct 1582 AD and that the next day would be 15 Oct 1582 in the 
  41. ** Gregorian Calendar.  The only other change is that centesimal 
  42. ** years (years ending in 00) would no longer be leap years 
  43. ** unless divisible by 400.  Britain and its possessions and 
  44. ** colonies continued to use the Julian calendar up until 2 Sep 
  45. ** 1752, when the next day became 14 Sep 1752 in the Gregorian 
  46. ** Calendar.  These routines can be compiled to use either 
  47. ** convention.  By default, the British convention will be used.  
  48. ** Simply #define PAPAL to use Pope Gregory's convention. 
  49. ** 
  50. ** Each routine takes, as its last argument, a flag to indicate 
  51. ** whether to use the Julian or Gregorian calendar convention.  If 
  52. ** this flag is negative, the routines decide based on the date 
  53. ** itself, using the changeover date described in the preceding 
  54. ** paragraph.  If the flag is zero, Gregorian conventions will be used, 
  55. ** and if the flag is positive, Julian conventions will be used. 
  56. */
  57.  
  58.  
  59. #ifdef PAPAL                    /* Pope Gregory XIII's decree */
  60. #define LASTJULDATE 15821004L   /* last day to use Julian calendar */
  61. #define LASTJULJDN  2299160L    /* jdn of same */
  62. #else                           /* British-American usage */
  63. #define LASTJULDATE 17520902L   /* last day to use Julian calendar */
  64. #define LASTJULJDN  2361221L    /* jdn of same */
  65. #endif
  66.  
  67.  
  68. long ymd_to_jdn(int y, int m, int d, int julian)
  69. {
  70.         long jdn;
  71.  
  72.         if (julian < 0)         /* set Julian flag if auto set */
  73.                 julian = (((y * 100L) + m) * 100 + d  <=  LASTJULDATE);
  74.  
  75.         if (y < 0)              /* adjust BC year */
  76.                 y++;
  77.  
  78.         if (julian)
  79.                 jdn = 367L * y - 7 * (y + 5001L + (m - 9) / 7) / 4
  80.                 + 275 * m / 9 + d + 1729777L;
  81.         else
  82.                 jdn = (long)(d - 32076)
  83.                 + 1461L * (y + 4800L + (m - 14) / 12) / 4
  84.                 + 367 * (m - 2 - (m - 14) / 12 * 12) / 12
  85.                 - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4
  86.                 + 1;            /* correction by rdg */
  87.  
  88.         return jdn;
  89. }
  90.  
  91.  
  92. void jdn_to_ymd(long jdn, int *yy, int *mm, int *dd, int julian)
  93. {
  94.         long x, z, m, d, y;
  95.         long daysPer400Years = 146097L;
  96.         long fudgedDaysPer4000Years = 1460970L + 31;
  97.  
  98.         if (julian < 0)                 /* set Julian flag if auto set */
  99.                 julian = (jdn <= LASTJULJDN);
  100.  
  101.         x = jdn + 68569L;
  102.         if ( julian )
  103.         {
  104.                 x += 38;
  105.                 daysPer400Years = 146100L;
  106.                 fudgedDaysPer4000Years = 1461000L + 1;
  107.         }
  108.         z = 4 * x / daysPer400Years;
  109.         x = x - (daysPer400Years * z + 3) / 4;
  110.         y = 4000 * (x + 1) / fudgedDaysPer4000Years;
  111.         x = x - 1461 * y / 4 + 31;
  112.         m = 80 * x / 2447;
  113.         d = x - 2447 * m / 80;
  114.         x = m / 11;
  115.         m = m + 2 - 12 * x;
  116.         y = 100 * (z - 49) + y + x;
  117.  
  118.         *yy = y;
  119.         *mm = m;
  120.         *dd = d;
  121.  
  122.         if (*yy <= 0)                   /* adjust BC years */
  123.                 (*yy)--;
  124. }
  125.